<?php

namespace App\Http\Controllers;

use App\Models\MchOrder;
use App\Models\Member;
use App\Models\Setting;
use App\Models\SettingFinance;
use App\Models\SettingGain;
use App\Models\SettingWechat;
use App\Models\Share;
use App\Traits\CheckMessageNotice;
use App\Traits\SubscribeMessage;
use EasyWeChat\Factory;
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
use Illuminate\Foundation\Bus\DispatchesJobs;
use Illuminate\Foundation\Validation\ValidatesRequests;
use Illuminate\Routing\Controller as BaseController;
use Illuminate\Support\Facades\Crypt;
use Illuminate\Support\Facades\DB;
use Kuyuan\Phpwidget\File;

class Controller extends BaseController
{
    use AuthorizesRequests, DispatchesJobs, ValidatesRequests, CheckMessageNotice, SubscribeMessage;

    // 微信支付证书cert
    private $_cert_path = '';
    // 微信支付证书key
    private $_key_path = '';

    /**
     * 获取系统所有配置
     * @return mixed
     */
    protected function getConfig()
    {
        $Setting = Setting::first();
        $Setting->wechat;
        $Setting->pay;
        $Setting->media;
        $Setting->finance;
        $Setting->gain;
        $Setting->message;
        return $Setting;
    }

    /**
     * 获取微信公众号配置
     */
    private function getWechatConfig()
    {
        $Setting = Setting::first();
        $Setting->wechat;
        $Setting->pay;
        $_setting = $Setting->toArray();
        return [
            'app_id' => $_setting['wechat']['wechat_appid'],
            'secret' => $_setting['wechat']['wechat_secret'],
            'token' => $_setting['wechat']['wechat_token'],
            'aes_key' => $_setting['wechat']['wechat_encoding_key'],
            'response_type' => 'array'
        ];
    }

    /**
     * 获取指定的配置信息
     * @param array $_fields 配置字段
     * @param string $_setting_type
     * @return mixed
     */
    protected function getOnceConfig(Array $_fields = array(),$_setting_type = 'base')
    {
        $Setting = null;
        switch ($_setting_type) {
            case 'base':
                $Setting = Setting::select($_fields)->first();
                break;
            case 'wechat':
                $Setting = SettingWechat::select($_fields)->first();
                if(isset($Setting->wechat_qrcode)) {
                    $Setting->wechat_qrcode = cool_media($Setting->wechat_qrcode);
                }
                if(isset($Setting->wechat_logo)) {
                    $Setting->wechat_logo = cool_media($Setting->wechat_logo);
                }
                break;
            case 'finance':
                $Setting = SettingFinance::select($_fields)->first();
                break;
            case 'gain':
                $Setting = SettingGain::select($_fields)->first();
                break;
        }
        return $Setting;
    }

    /**
     * 返回微信公账号接口对象
     */
    protected function wechat()
    {
        return Factory::officialAccount($this->getWechatConfig());
    }

    /**
     * 获取微信支付对象
     * @param string $_notify_route
     * @param boolean $_cert 是否生成支付证书
     * @return \EasyWeChat\Payment\Application
     */
    protected function wechatPay($_cert = false,$_notify_route = 'notifySendRed')
    {
        $Setting = $this->getConfig();
        $_setting_array = [
            'app_id' => $Setting->wechat->wechat_appid,
            'mch_id' => $Setting->pay->wechat_mch_account,
            'key' => $Setting->pay->wechat_mch_key,
            'notify_url' => route($_notify_route)
        ];
        if($_cert) {
            $this->_cert_path = $_setting_array['cert_path'] = storage_path('app/wechat_pay_cert/'.File::fileName('pem'));
            $this->_key_path = $_setting_array['key_path'] = storage_path('app/wechat_pay_cert/'.File::fileName('pem'));
            file_put_contents($this->_cert_path,Crypt::decryptString($Setting->pay->wechat_cert));
            file_put_contents($this->_key_path,Crypt::decryptString($Setting->pay->wechat_key));
        }
        return Factory::payment($_setting_array);
    }

    /**
     * 企业支付到用户零钱
     * @param int $_money 金额
     * @param string $_source
     * @param string $_source_id
     * @param int $_member_id
     * @param string $_desc
     * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException
     * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
     * @throws \GuzzleHttp\Exception\GuzzleException
     */
    protected function toBalance(
        $_money, // 金额
        $_source, // 商户资金操作类型 red=发红包 open=开红包直接提现到微信余额 deposit=提现 open-award=企业支付到零钱
        $_source_id, // 资源id 红包id 或者提现id
        $_member_id = 0, // 会员id
        $_desc = '' // 说明
    )
    {
        $Setting = $this->getConfig();
        $Wechat = $this->wechatPay(true);
        if(!$_member_id) {
            $_member_id = auth('member')->id();
        }
        $_desc = empty($_desc) ? $Setting->website_name.'-红包到账' : $Setting->website_name.'-'.$_desc;
        $_order_id = $this->createMchOrder($_money,$_source,$_source_id,$_member_id);
        $_pay_result = $Wechat->transfer->toBalance([
            'partner_trade_no' => $_order_id,
            'openid' => Member::where("id",$_member_id)->value('openid'),
            'check_name' => 'NO_CHECK',
            'amount' => $_money,
            'desc' => $_desc
        ]);
        $this->clearPayCert();
        if($_pay_result['return_code'] == 'SUCCESS' && $_pay_result['result_code'] == 'SUCCESS') {
            MchOrder::where('order_id',$_order_id)->update([
                'status' => 2
            ]);
            return array('code'=>200);
        } else {
            return array(
                'code'=>402,
                'message'=>$_pay_result['return_msg'] ? $_pay_result['return_msg'] : $_pay_result['err_code_des']
            );
        }
    }

    /**
     * 退款
     */
    protected function refund(
        $_money, // 金额
        $_source, // 商户资金操作类型 red-refund=红包删除退款
        $_source_id, // 资源id 红包id 或者提现id
        $_member_id = 0, // 会员id
        $_desc = '' // 说明
    )
    {
        $Setting = $this->getConfig();
        $Wechat = $this->wechatPay(true);
        if(!$_member_id) {
            $_member_id = auth('member')->id();
        }
        $_desc = empty($_desc) ? $Setting->website_name.'-红包删除，剩余未发红包余额退款' : $Setting->website_name.'-'.$_desc;
        // 退款订单号
        $_order_id = $this->createMchOrder($_money,$_source,$_source_id,$_member_id);
        // 商户支付订单号
        $MchOrder = MchOrder::where("source","red")
            ->where("source_id",$_source_id)
            ->where("status",2)
            ->select('order_id','money')
            ->first();
        // 退款
        $_result = $Wechat->refund->byOutTradeNumber(
            $MchOrder->order_id,
            $_order_id,
            $MchOrder->money,
            $_money,
            ['refund_desc' => $_desc]
        );
        $this->clearPayCert();
        return $_result;
    }

    /**
     * 创建商户订单号
     */
    private function createMchOrder($_money,$_source,$_source_id,$_member_id)
    {
        $_order_id = ''.mt_rand(10000,99999).time();
        if(MchOrder::where('order_id',$_order_id)->exists()) {
            return $this->createMchOrder($_money,$_source,$_source_id,$_member_id);
        }
        MchOrder::create([
            'member_id' => $_member_id,
            'order_id' => $_order_id,
            'money' => $_money,
            'source' => $_source,
            'source_id' => $_source_id
        ]);
        return $_order_id;
    }

    /**
     * 清空支付证书
     */
    private function clearPayCert()
    {
        @unlink($this->_cert_path);
        @unlink($this->_key_path);
    }

    /**
     * 用户余额
     * @param int $_member_id
     * @return mixed
     */
    protected function balance($_member_id = 0)
    {
        if(!$_member_id) $_member_id = auth('member')->id();
        return Member::where('id', $_member_id)->value('balance');
    }

    /**
     * 操作用户余额
     * @param int $_balance 操作余额
     * @param boolean $_type true=新增余额  false=减去余额
     * @param int $_member_id 会员id
     * @return boolean
     */
    protected function balanceHandle($_balance,$_type = true,$_member_id = 0)
    {
        if(!$_member_id) $_member_id = auth('member')->id();
        $Member = Member::where('id', $_member_id)->first();
        if($_type) {
            $_result = $Member->increment('balance', $_balance);
        } else {
            $_result = $Member->decrement('balance', $_balance);
        }
        return $_result;
    }

    /**
     * 获取分享id
     * @param $_red_id
     * @return mixed
     */
    protected function getShareId($_red_id)
    {
        $_member_id = auth("member")->id();
        $Share = DB::table('shares')
                    ->where("member_id",$_member_id)
                    ->where("red_id",$_red_id)
                    ->first();
        if($Share){
            $_share_id = $Share->id;
        } else {
            $_share_id = $this->uniqidShareId();
            Share::create([
                "id" => $this->uniqidShareId(),
                "member_id" => $_member_id,
                "red_id" => $_red_id
            ]);
        }
        return $_share_id;
    }

    /**
     * 生成一个分享唯一id
     */
    private function uniqidShareId()
    {
        $_share_id = \Illuminate\Support\Str::random(8);
        if(Share::where("id",$_share_id)->exists()) {
            return $this->uniqidShareId();
        }
        return $_share_id;
    }
}
